package com.yk.system.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yk.api.system.dto.ConfigurationRoleDTO;
import com.yk.api.system.dto.MessageDTO;
import com.yk.api.system.dto.UserConfigurationRoleDTO;
import com.yk.common.core.constant.NumberConstant;
import com.yk.common.core.domain.BasePageQuery;
import com.yk.common.core.domain.LoginUser;
import com.yk.common.core.domain.PageResult;
import com.yk.common.core.domain.Result;
import com.yk.common.core.enums.RoleTypeEnum;
import com.yk.common.core.utils.LoginHelper;
import com.yk.system.convert.ConfigurationRoleConvert;
import com.yk.system.entity.Configuration;
import com.yk.system.entity.ConfigurationRole;
import com.yk.system.entity.Message;
import com.yk.system.entity.User;
import com.yk.system.service.ConfigurationRoleService;
import com.yk.system.service.ConfigurationService;
import com.yk.system.service.MessageService;
import com.yk.system.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;


/**
 * 组态分享 yk-system
 *
 * @author lmx
 * @since 2024-04-24
 */
@Api(tags = "组态分享控制器")
@RestController
@RequestMapping("/configurationRole")
@RequiredArgsConstructor
public class ConfigurationRoleController {

    private final ConfigurationRoleService configurationRoleService;
    private final ConfigurationService configurationService;
    private final ConfigurationRoleConvert configurationRoleConvert;
    private final UserService userService;
    private final MessageService messageService;

    @GetMapping("/getById/{id}")
    @ApiOperation("查询单个")
    public Result<ConfigurationRole> getById(@PathVariable(value = "id") Long id) {
        return Result.data(configurationRoleService.getById(id));
    }

    @PostMapping("/update")
    @ApiOperation("修改")
    public Result<Boolean> updateById(@RequestBody ConfigurationRoleDTO dto) {
        configurationRoleService.updateConfigurationRole(configurationRoleConvert.dto2Entity(dto));
        return Result.ok();
    }

    @GetMapping("/deleteById/{id}")
    @ApiOperation("删除")
    public Result<Boolean> deleteById(@PathVariable(value = "id") Long id) {
        return Result.data(configurationRoleService.removeById(id));
    }

    @PostMapping("/list")
    @ApiOperation("查询列表")
    public Result<List<ConfigurationRoleDTO>> list(@RequestBody ConfigurationRoleDTO param) {
        Assert.notNull(param.getConfigurationId(), "组态ID不能为空");
        List<ConfigurationRoleDTO> list = CollUtil.newArrayList();
        LambdaQueryWrapper<ConfigurationRole> lambda = new LambdaQueryWrapper<>();
        buildCondition(lambda, param);
        configurationRoleService.list(lambda).forEach(it -> list.add(configurationRoleConvert.entity2Dto(it)));
        list.forEach(configurationRoleService::assignConfigurationRole);
        return Result.data(list);
    }

    @GetMapping("/unReception/{configurationId}")
    @ApiOperation("断开接收")
    public Result<Boolean> unReception(@PathVariable Long configurationId) {
        Long userId = LoginHelper.getLoginUserId();
        LambdaQueryWrapper<ConfigurationRole> lambda = new LambdaQueryWrapper<>();
        lambda.eq(ConfigurationRole::getUserId, userId);
        lambda.eq(ConfigurationRole::getConfigurationId, configurationId);
        lambda.eq(ConfigurationRole::getStatus, NumberConstant.ZERO_STR);
        ConfigurationRole configurationRole = configurationRoleService.getOne(lambda);
        Assert.notNull(configurationRole, "组态权限不存在");
        if (RoleTypeEnum.ADMIN.getCode().equals(configurationRole.getRoleType())) {
            return Result.fail("管理员不能断开接收");
        }
        configurationRole.setStatus(NumberConstant.ONE_STR);
        configurationRoleService.updateById(configurationRole);
        // 发送系统通知
        LoginUser loginUser = LoginHelper.getLoginUser();
        Configuration configuration = configurationService.getById(configurationRole.getConfigurationId());
        String message = loginUser.getNickname() + "断开分享组态：" + configuration.getName();
        messageService.systemMessage("组态断开分享通知", configurationRole.getAdminId(), message, NumberConstant.ZERO_STR);
        return Result.ok();
    }

    @PostMapping("/page")
    @ApiOperation("分页查询")
    public PageResult<ConfigurationRoleDTO> page(@RequestBody BasePageQuery<ConfigurationRoleDTO> pageParam) {
        ConfigurationRoleDTO param = pageParam.getParam();
        Assert.notNull(param.getConfigurationId(), "组态ID不能为空");
        ConfigurationRole configurationRole = configurationRoleService.getConfigurationRole(param.getConfigurationId());
        if (Objects.isNull(configurationRole)) {
            return PageResult.success(CollUtil.newArrayList(), 0);
        }
        if (!RoleTypeEnum.ADMIN.getCode().equals(configurationRole.getRoleType())
                && !RoleTypeEnum.MANAGE.getCode().equals(configurationRole.getRoleType())) {
            return PageResult.success(CollUtil.newArrayList(), 0);
        }
        LambdaQueryWrapper<ConfigurationRole> lambda = new LambdaQueryWrapper<>();
        buildCondition(lambda, param);
        IPage<ConfigurationRoleDTO> page = configurationRoleService.page(new Page<>(pageParam.getPageNum(),
                pageParam.getPageSize()), lambda).convert(configurationRoleConvert::entity2Dto);
        page.getRecords().forEach(configurationRoleService::assignConfigurationRole);
        return PageResult.success(page.getRecords(), page.getTotal());
    }

    /**
     * 构造查询条件
     *
     * @param lambda 表达式
     * @param param  参数
     */
    private void buildCondition(LambdaQueryWrapper<ConfigurationRole> lambda, ConfigurationRoleDTO param) {
        lambda.eq(Objects.nonNull(param.getConfigurationId()), ConfigurationRole::getConfigurationId,
                param.getConfigurationId());
        if (StrUtil.isNotEmpty(param.getRoleType())) {
            lambda.eq(ConfigurationRole::getRoleType, param.getRoleType());
        } else {
            lambda.in(ConfigurationRole::getRoleType, RoleTypeEnum.getConditions());
        }
        lambda.eq(StrUtil.isNotEmpty(param.getStatus()), ConfigurationRole::getStatus, param.getStatus());
        lambda.between(Objects.nonNull(param.getStartTime()), ConfigurationRole::getCreatedAt, param.getStartTime(),
                param.getEndTime());
        lambda.orderByAsc(ConfigurationRole::getStatus);
        lambda.orderByDesc(ConfigurationRole::getUpdatedAt);
    }

    @PostMapping("/phone")
    @ApiOperation("管理者共享手机号")
    public Result<Boolean> message2Phone(@RequestBody @Validated ConfigurationRoleDTO dto) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        Assert.notNull(dto.getPhone(), "手机号不能为空");
        Assert.notNull(dto.getConfigurationId(), "组态id不能为空");
        LambdaQueryWrapper<User> lambda = new LambdaQueryWrapper<>();
        lambda.eq(User::getUserName, dto.getPhone()).or().eq(User::getPhone, dto.getPhone());
        User user = userService.getOne(lambda);
        Assert.notNull(user, "用户不存在");
        Configuration configuration = configurationService.getById(dto.getConfigurationId());
        Assert.notNull(configuration, "组态不存在");
        messageService.checkShare(user.getId(), loginUser.getUserId(), NumberConstant.TWO_STR, configuration.getId());
        configurationRoleService.checkShare(dto.getConfigurationId(), "对方已接收该组态", user.getId());
        dto.setUserId(user.getId());
        dto.setAdminId(loginUser.getUserId());
        ConfigurationRole configurationRole = configurationRoleConvert.dto2Entity(dto);
        long configurationRoleId = IdWorker.getId();
        configurationRole.setId(configurationRoleId);
        configurationRole.setDelFlag(NumberConstant.TWO_STR);
        configurationRoleService.save(configurationRole);
        messageService.configurationShareMessage("向" + user.getNickName() + "共享了组态" + configuration.getName(),
                loginUser.getUserId(), user.getId(), configurationRoleId, null, configuration.getId());
        messageService.configurationSharedMessage(loginUser.getNickname() + "向您共享了组态" + configuration.getName(),
                loginUser.getUserId(), user.getId(), configurationRoleId, null, configuration.getId());
        return Result.ok();
    }

    @PostMapping("/save/phone")
    @ApiOperation("接收者接收手机号")
    public Result<Boolean> save2Phone(@RequestBody @Validated MessageDTO dto) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        Assert.notNull(dto.getReceiveStatus(), "接收状态不能为空");
        Assert.notNull(dto.getId(), "消息Id不能为空");
        Message message = messageService.getById(dto.getId());
        Assert.notNull(message, "消息不存在");
        Assert.notNull(message.getDeviceRoleId(), "接收失败");
        ConfigurationRole configurationRole = configurationRoleService.getByIdIgnoreDel(message.getDeviceRoleId());
        Assert.notNull(configurationRole, "分享已失效");
        if (NumberConstant.ZERO_STR.equals(configurationRole.getDelFlag())) {
            message.setReceiveStatus(dto.getReceiveStatus());
            messageService.updateById(message);
            return Result.fail("该组态已接收");
        }
        Configuration configuration = configurationService.getById(configurationRole.getConfigurationId());
        if (dto.getReceiveStatus()) {
            configurationRole.setDelFlag(NumberConstant.ZERO_STR);
            configurationRoleService.updateDelConfigurationRole(configurationRole);
            messageService.configurationShareMessage(loginUser.getNickname() + "接收了您分享的组态" + configuration.getName(),
                    message.getShareId(), message.getSharedId(), configurationRole.getId(), Boolean.TRUE, configuration.getId());
        } else {
            messageService.configurationSharedMessage(loginUser.getNickname() + "拒绝接收您分享的组态" + configuration.getName(),
                    message.getShareId(), message.getSharedId(), configurationRole.getId(), Boolean.FALSE, configuration.getId());
        }
        message.setReceiveStatus(dto.getReceiveStatus());
        messageService.updateById(message);
        return Result.ok();
    }

    @GetMapping("/userConfigurationRole")
    @ApiOperation("获取当前用户的组态权限")
    public Result<List<UserConfigurationRoleDTO>> userConfigurationRole() {
        Long userId = LoginHelper.getLoginUserId();
        LambdaQueryWrapper<ConfigurationRole> lambda = new LambdaQueryWrapper<>();
        lambda.select(ConfigurationRole::getConfigurationId, ConfigurationRole::getRoleType,
                ConfigurationRole::getExpiredTime);
        lambda.eq(ConfigurationRole::getUserId, userId);
        lambda.eq(ConfigurationRole::getStatus, NumberConstant.ZERO_STR);
        List<ConfigurationRole> list = Optional.ofNullable(configurationRoleService.list(lambda))
                .orElse(CollUtil.newArrayList());
        List<UserConfigurationRoleDTO> returnList = list.stream().map(item -> {
            UserConfigurationRoleDTO dto = new UserConfigurationRoleDTO();
            dto.setConfigurationId(item.getConfigurationId());
            dto.setRoleType(item.getRoleType());
            Date date = DateUtil.parseDateTime("9999-12-31 00:00:00");
            if (Objects.nonNull(item.getExpiredTime()) && date.compareTo(item.getExpiredTime()) != 0) {
                dto.setExpiredTime(item.getExpiredTime());
            }
            return dto;
        }).collect(Collectors.toList());
        return Result.data(returnList);
    }

    @ApiOperation("查询组态权限码")
    @GetMapping("/getRoleCode/{configurationId}")
    public Result<String> getRoleCode(@PathVariable Long configurationId) {
        ConfigurationRole configurationRole = configurationRoleService.getConfigurationRole(configurationId);
        if (Objects.isNull(configurationRole)) {
            return Result.data(RoleTypeEnum.VIEW.getCode());
        }
        return Result.data(configurationRole.getRoleType());
    }

}